/*
* ====================================================================
* Copyright (c) 2013-2014 Neudesic.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that redistributions of source
* retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* This source file includes software written by Neudesic, LLC (http://www.neudesic.com).
*
* THIS SOFTWARE IS PROVIDED BY Neudesic, LLC ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  FURTHER, IN NO EVENT SHALL
* Neudesic, LLC (THE AUTHOR) OR ANY CONTRIBUTORS BE LIABLE FOR ANY DAMAGES
* WHATSOEVER THAT ARE RELATED TO THE SOFTWARE [INCLUDING BUT NOT LIMITED TO,
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* SUCH AS LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION, HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)] EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
*
* ====================================================================
*/
#ifndef __ISOCKETCONTAINER_H__
#define __ISOCKETCONTAINER_H__

#include "winrtsock.h"
#include <winapifamily.h>
#include <wrl.h>
#include <windows.storage.streams.h>
#include <windows.networking.sockets.h>
#include <string>
#include "winrtutils.h"
#include "SocketInformation.h"

using Microsoft::WRL::ComPtr;
using ABI::Windows::Storage::Streams::IOutputStream;
using ABI::Windows::Storage::Streams::IDataReader;
using ABI::Windows::Networking::Sockets::IStreamSocket;
using ABI::Windows::Foundation::IAsyncAction;
using ABI::Windows::Networking::IHostName;
using ABI::Windows::Networking::HostNameType;
using ABI::Windows::Networking::Sockets::IDatagramSocket;

namespace Neudesic {
	namespace Sockets {
		
		enum SocketType
		{
			InvalidSocket = 0,
			StreamSocketType,
			DatagramSocketType
		};

		enum TimeoutDuration
		{
			Infinity = -1,
			Bind = 3000,
			Connect = 10000,
			Send = 10000,
			Receive = 10000,
			EndpointPairs = 1000,
			Quit = 1000
		};

		enum SocketContainerState
		{
			NotConnected,
			Bound,
			Connected,
			Closed,
		};

		interface ISocketContainer
		{
		public:
			virtual HRESULT Close() = 0;
			virtual HRESULT Connect(const struct sockaddr* name, int namelen) = 0;
			virtual HRESULT Connect(const struct sockaddr *name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS) = 0;
			virtual HRESULT EventSelect(WSAEVENT hEventObject, long lNetworkEvents) = 0;
			virtual HRESULT GetNetworkEvents(WSAEVENT hEventObject, LPWSANETWORKEVENTS lpNetworkEvents) = 0;
			virtual HRESULT GetPeerName(sockaddr* nameInfo, int* namelen) = 0;
			virtual HRESULT GetSocketName(sockaddr* nameInfo, int* namelen) const = 0;
			virtual SocketType GetSocketType() const = 0;
			virtual HRESULT GetUnconsumedBufferLength(long command, ULONG* argp) = 0;
			virtual bool IsRunning() const = 0;
			virtual HRESULT SetSocketOptions(int level, int optname, const char* optval, int optlen) = 0;
			virtual HRESULT SetWSAEvent(HANDLE hWSAEvent) = 0;
			virtual HRESULT Shutdown(int how) = 0;
		protected:
			virtual HRESULT ConnectSocket(const ComPtr<IHostName>& hostName, const wchar_t* serviceName) = 0;
			virtual HRESULT InternalReceive(char *buf, int len, int flags, LPDWORD lpNumberOfBytesRecvd) = 0;
		};

		template <typename T, typename TInfo>
		interface ITypedSocketContainer : ISocketContainer
		{
		public:
			virtual ComPtr<T> GetSocket() const = 0;
		};

		interface IDatagramSocketContainer
		{
		public:
		protected:
		};

		interface IStreamSocketContainer
		{
		public:
			//virtual HRESULT Listen(int backlog) = 0;
		protected:
		};

	}	//Sockets
}	//Neudesic

#endif